package com.xx.account.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.xx.account.domain.bo.ImageZipBo;
import com.xx.account.domain.bo.ImageZipDownloadBo;
import com.xx.account.service.IAccountDownloadImageService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Author: WangYang
 * Date: 2024/11/8 - 19:33
 */
@Service
public class AccountDownloadImageServiceImpl implements IAccountDownloadImageService {

    @Value("${ruoyi.profile}")
    private String path;

    @Override
    public ResponseEntity downloadImageZip(ImageZipDownloadBo bo, HttpServletResponse response) {

        // 生成一个新文件夹，用于存储下载的图片
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dirName = sdf.format(new Date()) + "-" + bo.getFileName();
        String saveDirectory = path + dirName; // 保存文件路径
        String zipFilePath = saveDirectory + ".zip"; // 压缩包路径

        try {
            // 创建图片保存目录（如果目录不存在）
            File dir = new File(saveDirectory);
            if (!dir.exists()) {
                dir.mkdirs(); // 使用 mkdirs() 创建目录和父目录
            }
            // 遍历列表，获取图片
            for (ImageZipBo imageZipBo : bo.getImageZipBoList()) {
                String url = imageZipBo.getUrl();
                // 解析页面
                Document doc = Jsoup.connect(url).get();
                if("1".equals(imageZipBo.getType())){
                    // 可乐
                    // 查找包含页码信息的 <label> 标签
                    Element labelElement = doc.select("label").last();
                    // 获取标签中的文本内容
                    String labelText = labelElement.text().trim();
                    // 提取总页数
                    int page = Integer.parseInt(labelText.split("/")[1]);
                    for (int i = 1; i <= page; i++) {
                        // 下载图片到指定目录
                        String newUrl = url.replaceAll(",\\d+,", "," + i + ",");
                        downloadImagesFromPage(newUrl, saveDirectory);
                    }
                }else if("2".equals(imageZipBo.getType())){
                    // 下单
                    for (int i = 1; i <= 30; i++) {
                        // 下载图片到指定目录
                        downloadImagesFromPage(url + "?page=" + i, saveDirectory);
                    }
                }
            }

            System.out.println("图片下载完成，保存路径：" + saveDirectory);
            // 将下载的图片文件夹压缩成一个 zip 文件
            zipDirectory(saveDirectory, zipFilePath);
            System.out.println("压缩包已生成: " + zipFilePath);
            // 获取压缩包的字节流，用于返回到页面下载
            File zipFile = new File(zipFilePath);
            byte[] zipBytes = readFileToByteArray(zipFile);
            // 设置返回的响应头，表明返回的是一个文件流
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFile.getName()));
            headers.add("Content-Length", "" + zipFile.length());

            return ResponseEntity.ok().headers(headers).body(zipBytes);  // 返回压缩包字节流
        } catch (IOException e) {
            System.err.println("操作失败：" + e.getMessage());
            e.printStackTrace();
            return null;
        }finally {
            // 步骤3: 删除文件夹和压缩包
            deleteDirectory(new File(saveDirectory));
            System.out.println("已删除图片文件夹: " + saveDirectory);
            File zipFile = new File(zipFilePath);
            if (zipFile.delete()) {
                System.out.println("已删除压缩包: " + zipFilePath);
            } else {
                System.out.println("删除压缩包失败: " + zipFilePath);
            }
        }
    }

    private byte[] readFileToByteArray(File file) throws IOException {
        try (InputStream inputStream = new FileInputStream(file);
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[1024];
            int bytesRead;

            // 读取文件流并写入 ByteArrayOutputStream
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }

            // 返回字节数组
            return byteArrayOutputStream.toByteArray();
        }
    }

    // 下载图片并保存到指定的路径
    public static void downloadImage(String imageUrl, String destinationFile) throws IOException {
        URL url = new URL(imageUrl);
        try (InputStream in = url.openStream(); FileOutputStream out = new FileOutputStream(destinationFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
    }

    public static String generateRandomString() {
        // 可选字符集，包括大写字母、小写字母和数字
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuilder result = new StringBuilder();

        // 生成随机字符串
        for (int i = 0; i < 20; i++) {
            // 随机选择字符集中的一个字符
            int index = random.nextInt(characters.length());
            result.append(characters.charAt(index));
        }

        return result.toString();
    }

    // 将目录中的所有图片打包成 zip 文件
    public static void zipDirectory(String sourceDirPath, String zipFilePath) throws IOException {
        File sourceDir = new File(sourceDirPath);
        try (FileOutputStream fos = new FileOutputStream(zipFilePath);
             ZipOutputStream zipOut = new ZipOutputStream(fos)) {
            File[] files = sourceDir.listFiles();
            if (files != null) {
                for (File file : files) {
                    try (FileInputStream fis = new FileInputStream(file)) {
                        ZipEntry zipEntry = new ZipEntry(file.getName());
                        zipOut.putNextEntry(zipEntry);
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = fis.read(buffer)) != -1) {
                            zipOut.write(buffer, 0, bytesRead);
                        }
                        zipOut.closeEntry();
                    }
                }
            }
        }
    }

    // 从页面抓取图片链接并下载到指定目录
    public static void downloadImagesFromPage(String pageUrl, String saveDirectory) throws IOException {
        // 解析页面
        Document doc = Jsoup.connect(pageUrl).get();

        // 提取所有图片元素
        Elements imgElements = doc.select("img[src]");

        int imageCount = 0;
        for (Element imgElement : imgElements) {
            String imgSrc = imgElement.absUrl("src"); // 获取完整的图片 URL
            if (imgSrc != null && !imgSrc.isEmpty()) {
                // 给图片起一个本地文件名，使用图片的 URL 最后一个部分作为文件名
                String fileName = saveDirectory + "/image_" + generateRandomString() + ".jpg";
                downloadImage(imgSrc, fileName);
                System.out.println("下载图片: " + imgSrc);
            }
        }
    }

    // 删除目录及其内容
    public static void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file); // 递归删除
                }
            }
        }
        // 删除文件或空目录
        if (directory.delete()) {
            System.out.println("已删除文件或目录: " + directory.getAbsolutePath());
        } else {
            System.err.println("删除失败: " + directory.getAbsolutePath());
        }
    }

}
